<?php
namespace app\helpers;
use Yii;
use app\helpers\XapiHttpHandler;

define('CACHE_PREFIX_TIME', "key_time_");
define('CACHE_PREFIX_DATA', "key_data_");
define('CACHE_EXPIRE_DEFAULT', 86400);
define('MAX_LEN_KEY', 250);
define('CACHE_FLAG_NO_EXPIRE', 0);
define('CACHE_FLAG_NO_CACHE', -1);
define('CACHE_FLAG_FLUSH', -2);
define('CACHE_FLUSH_WEB', 1);
define('CACHE_FLUSH_PROCESS', 2);
define('CACHE_EXPIRE', 300);



/**
 * 单例的HTTP CUR CLIENT 获取接口内容
 */
class XapiClient
{
    private static $_http = null;
    private static $_cookie_sid = null;
    private static $_stat_request_count = 0;
    private static $_stat_request_exec_time = 0;
    public static $_debug_api_log = '';
    private static $_inc = 0;
    protected $_user_request_info = '';
    protected $_curl_request_info = '';
    protected $_response_from_curl = '';
    protected $_response_from_our = '';
    const API_REQUEST_TIMEOUT = 8000;

    /**
     * 获取单例对象
     */
    private static function _getHttp($time_out = 0)
    {
        // 不同的curl实例对象需要不同的超时时间，需要以时间关联的key 2015-11-20
        if ($time_out == 0) {
            global $g_switch_conf;
            if (isset($g_switch_conf['GATEWAY_CURL_TIMEOUT_MS']) && $g_switch_conf['GATEWAY_CURL_TIMEOUT_MS'] > 0) {
                $time_out = $g_switch_conf['GATEWAY_CURL_TIMEOUT_MS'];
            } else {
                $time_out = self::API_REQUEST_TIMEOUT;
            }
        }
        $key = 'TIMEOUT:'.$time_out;
        if (@self::$_http[$key] == null) {
            self::$_http[$key] = new XapiHttpHandler(XapiHttpHandler::CHARSET_UTF8, $time_out);
        }
        return self::$_http[$key];
    }

    /**
     * 获取当前环境对应的 api url（生产、预发布返回生产api）
     * @todo 暂时这样处理，上线后重构
     * @author zhanglibin
     */
    private static function _getUrlByEnv($url)
    {
        return $url;
    }

    private static function logAndReturn($method, $url, $query, $opts, $assoc, $response, $runtime_ms, $timeout_ms)
    {
        self::$_stat_request_count++;
        self::$_stat_request_exec_time += $runtime_ms;

        $ret = null;
        $status = 1004;
        $message = '请求发生错误';

        //log info  yii::info($reqInfo ,self::LOG_ID_REQUEST);
        $requestInfo = "!! method:$method | url:[$url] | request-query" . (is_array($query) ? json_encode($query) : $query ) . " ~!!";
        yii::info($requestInfo ,'api_request');
        //response
        yii::info("!! " . (is_array($response) ? json_encode($response) : $response) . " ~!!",'api_response');

        if ($runtime_ms > $timeout_ms && empty($response)) {
            $status = 408;
            $message = '请求超时，请稍后重试';

        } else if (!json_decode($response)) {
            $ret = $response;
        } else {
            $ret = json_decode($response, $assoc);

            if (is_array($ret) && isset($ret['status'])) {
                $status = $ret['status'] + 0;
                $message = !empty($ret['message']) ? @$ret['message'] : @$ret['msg'];
                // 统一修改服务器超时文案
                if (504 == $status)
                    $message = $ret['message'] = '服务超时，请稍后重试';
            } else if (is_object($ret) && isset($ret->status)) {
                $status = $ret->status + 0;
                $message = $ret->message ?: $ret->msg;
                if (504 == $status)
                    $message = $ret->message = '服务超时，请稍后重试';
            }
        }
        //返回 给客户端信息
        yii::info("!!status:" . $status . ",message :" . $message . " ~!!",'api_return');

        return $ret;
    }

    /**
     * GET 获取数据
     * @param string $url 接口链接
     * @param bool $assoc
     * @param int $timeout_ms 请求过期时间
     * @return mixed|null
     */
    public static function ApiGet($url, $assoc = true, $timeout_ms = 0)
    {
        $url = self::_getUrlByEnv($url);
        $_http = self::_getHttp($timeout_ms);

        $_opts = array(
            'cookies' => 'sid=' . self::$_cookie_sid
        );
        $start = microtime(TRUE);
        $api_response = $_http->get($url, array(), $_opts);
        $end = microtime(TRUE);
        $runtime_ms = intval((($end - $start) * 1000000)) / 1000;

        return self::logAndReturn('GET', $url, array(), $_opts, $assoc, $api_response, $runtime_ms, $timeout_ms);
    }

    /**
     * POST 获取数据
     * @param string $url 接口链接
     * @param array $query 数据
     * @param int $timeout_ms 请求过期时间
     * @return mixed|null
     */
    public static function ApiPost($url, $query, $opts = array(), $timeout_ms = 0)
    {
        $url = self::_getUrlByEnv($url);
        $_http = self::_getHttp($timeout_ms);

        $_opts = $opts;
        if (self::$_cookie_sid)
            $_opts['cookies'] = 'sid=' . self::$_cookie_sid;

        $start = microtime(TRUE);
        $api_response = $_http->post($url, $query, array(), $_opts);
        $end = microtime(TRUE);
        $runtime_ms = intval((($end - $start) * 1000000)) / 1000;

        return self::logAndReturn('POST', $url, $query, $_opts, true, $api_response, $runtime_ms, $timeout_ms);
    }
    /**
     * POST提交json数据
     * @param sting $url 接口链接
     * @param array  $query 数据
     * @param int $timeout 请求过期时间
     */
    public static function ApiPostJson($url, $query, $opts = array(), $timeout_ms = 0) {

        $url = self::_getUrlByEnv($url);
        $_http = self::_getHttp($timeout_ms);

        $_opts = $opts;
        if (self::$_cookie_sid)
            $_opts['cookies'] = 'sid=' . self::$_cookie_sid;

        $start = microtime(TRUE);
        $api_response = $_http->postJson($url, $query, array(), $_opts);
        $end = microtime(TRUE);
        $runtime_ms = intval((($end - $start) * 1000000)) / 1000;

        return self::logAndReturn('POST', $url, $query, $_opts, true, $api_response, $runtime_ms, $timeout_ms);
    }
    /**
     * PUT 修改信息
     * @param string $url 接口链接
     * @param array $query 数据
     * @param int $timeout_ms 请求过期时间
     * @return mixed|null
     */
    public static function ApiPut($url, $query, $timeout_ms = 0)
    {
        $url = self::_getUrlByEnv($url);
        $_http = self::_getHttp($timeout_ms);

        $_opts = array(
            'cookies' => 'sid=' . self::$_cookie_sid
        );
        $start = microtime(TRUE);
        $api_response = $_http->put($url, $query, array(), $_opts);
        $end = microtime(TRUE);
        $runtime_ms = intval((($end - $start) * 1000000)) / 1000;

        return self::logAndReturn('PUT', $url, $query, $_opts, true, $api_response, $runtime_ms, $timeout_ms);
    }

    /**
     * PUT JSON add by zqy 2016-08-17
     * @param string $url 接口链接
     * @param array $query 数据
     * @param int $timeout_ms 请求过期时间
     * @return mixed|null
     */
    public static function ApiPutJson($url, $query, $timeout_ms = 0)
    {
        $url = self::_getUrlByEnv($url);
        $_http = self::_getHttp($timeout_ms);

        $_opts = array(
            'cookies' => 'sid=' . self::$_cookie_sid
        );
        $start = microtime(TRUE);
        $api_response = $_http->putJson($url, $query, array(), $_opts);
        $end = microtime(TRUE);
        $runtime_ms = intval((($end - $start) * 1000000)) / 1000;

        return self::logAndReturn('PUT', $url, $query, $_opts, true, $api_response, $runtime_ms, $timeout_ms);
    }

    /**
     * DELETE 删除信息
     * @param string $url 接口链接
     * @param string|array $query 数据
     * @param int $timeout_ms 请求过期时间
     * @return mixed|null
     */
    public static function ApiDelete($url, $query = '', $timeout_ms = 0)
    {
        $url = self::_getUrlByEnv($url);
        $_http = self::_getHttp($timeout_ms);

        $_opts = array(
            'cookies' => 'sid=' . self::$_cookie_sid
        );
        $start = microtime(TRUE);
        $api_response = $_http->delete($url, $query, array(), $_opts);
        $end = microtime(TRUE);
        $runtime_ms = intval((($end - $start) * 1000000)) / 1000;

        return self::logAndReturn('DELETE', $url, $query, $_opts, true, $api_response, $runtime_ms, $timeout_ms);
    }

    /**
     * POST 上传文件
     * @param string $url 接口链接
     * @param array $query 数据
     * @param int $timeout_ms 请求过期时间
     * @return mixed|null
     */
    public static function ApiPostFile($url, $query, $opts = array(), $timeout_ms = 0)
    {
        $url = self::_getUrlByEnv($url);
        $_http = self::_getHttp($timeout_ms);

        $_opts = $opts;
        if (self::$_cookie_sid)
            $_opts['cookies'] = 'sid=' . self::$_cookie_sid;

        $start = microtime(TRUE);
        $api_response = $_http->postFile($url, $query, array(), $_opts);
        $end = microtime(TRUE);
        $runtime_ms = intval((($end - $start) * 1000000)) / 1000;

        return self::logAndReturn('POST', $url, $query, $_opts, true, $api_response, $runtime_ms, $timeout_ms);
    }

    /**
     *  拼接url
     * @param $urlKey
     * @param string $gateway
     * @return string
     */
    public static function assembleUrl($urlKey,$gateway = 'ffan')
    {
        $gateways = Yii::$app->params['webcnf']['gateway'];
        $gatewayKeys = array_keys($gateways);
        $apiUrls = Yii::$app->params['apiurl'];
        $apiUrl = $_gateway = '';

        if(!in_array($gateway,$gatewayKeys)){
            return '';
        }else{
            $_gateway = $gateways[$gateway];
            $apiUrl = trim($_gateway,'/') . '/' . $apiUrls[$gateway][$urlKey];

        }

        return $apiUrl;
    }

}
